/**
 *  core.h - Task management.
 *
 *  Copyright (C) 2008-2010 ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef __CORE_H__
#define __CORE_H__

#include "include/types.h"

#ifndef UNIT_DEBUG
#include "include/list.h"
#include "include/mem.h"
#include "include/irq.h"
#endif


#ifndef stk_t
#define stk_t    int32
#endif

#define VERSION 100     // Version of Bycoe 1.0.0.

#define MAX_PRIO    64  // the max priority of task.
                        // The bigger, the lower priority.

#define READY_NUM   8   // the size of a array that used to find.
                        // out the next running task.

// Task status
#define T_READY  0x00   // Task is ready.
#define T_BLOCK  0x01   // Task is blocked.
#define T_SLEEP  0x02   // Task is sleep.
#define T_DELAY  0x03   // Task is delayed.


#define INIT_TASK_ID 99 // The ID of initial task, which is the first task,
                        // and it was created after the initialization.

#define INIT_TASK_PRIO 0         // The priority of initial task.
#define INIT_TASK_STACK_SIZE 512 // The stack length of initial task.

#define IDLE_TASK_ID 98 // The ID of idle task, which been to survive
                        // until the shutdown, and it is running when
                        // there is no task runs.

#define IDLE_TASK_PRIO (MAX_PRIO - 1)
#define IDLE_TASK_STACK_SIZE 32


// Task Control Block
typedef struct task_ctrl_blk {
    void *context;      // Pointer to context of task.
    void *pstart;       // Pointer to the first address of task space.

    list_t link;        // All tasks in a queue linked with this member.

    int32 id;          // Task ID.
    uint32 prio;       // Task priority.

    uint32 slice_time; // Slice time.
    uint32 exe_time;   // Executed time.
    int32 delay_time;  // Delayed time.
    uint32 status;     // Status, such as ready, delay, block as so on.
    slist_t sem_link;   // A sigle list poiter to a semaphore gained by task.
    list_t task_link;   // All tasks linked with this member.
} tcb_t;

extern uint32 get_isr_num(void); // Get the interrupted source number.
extern void Main(void);           // The entry routine of a application.

// The following routines are internal. Applications don't use them.
void add_tcb_rdy(tcb_t *ptcb);    // Add a TCB to ready queue
list_t *del_tcb_rdy(tcb_t *ptcb); // Delete a TCB from ready queue

void add_tcb_sleep(tcb_t *ptcb);  // Add a TCB to sleep queue

void lock_schedule(void);
void unlock_schedule(void);
uint32 if_isr(void);        // To determine whether the current context
                             // is in interruption state or not.

uint32 get_clock(void);     // Get the number of clock count.
tcb_t *current(void);        // Get the TCB of current task.

void scheduler(void);        // Scheduler the core of task management.
void sysinit(void);          // initialize function of Bycore.
void systick(void);          // The heart of Bycore, in fact, it is a
                             // interruption handle routine of a timer.


// Application Program Interfaces

#define osLockSchedule() lock_schedule()
#define osUnLockSchedule() unlock_schedule()

// osInitTask - It initializes a task with some parameters
extern void osInitTask(void(*pTask)(),     // Pointer to entry address of task.
                       int32 TaskID,      // Task ID.
                       uint32 Prio,       // Task priority.
                       uint32 Time,       // Task slice time.
                       uint32 StkSize);   // The size of stack.

/* osCreateTask - It initializes a task with some parameters.
 *    The differece between osCreateTask() and osInitTask()
 *    is that the former needs transfer a TCB and a stack space.
 */
extern void osCreateTask(void(*pTask)(),   // Pointer to entry address of task.
                         tcb_t *pTcb,      // Pointer to TCB of task.
                         int32 TaskID,    // Task ID.
                         uint32 Prio,     // Task priority.
                         uint32 Time,     // Task slice time.
                         stk_t *pStk,      // Pointer to stack space.
                         uint32 StkSize); // The size of stack.

extern void osChgPrio(uint32 NewPrio);// Change the priority of a task.
extern void osSleep(void);             // Make a task to sleep.
extern void osWakeUp(int32 TaskID);   // Wake up a sleep task.
extern void osWait(uint32 DelayTime); // Make a task to been delayed for while.
extern void osKill(void);              // Finish a life of a task.
extern uint32 osVersion(void);        // Get the current version of Bycore.
extern list_t *osGetTaskHead(void);    // Get the head of task list.
extern list_t *osGetSleepHead(void);   // Get the head sleep queue.
extern list_t *osGetDelayHead(void);   // Get the head delay queue.


#endif

